package viper

import (
	"fmt"
	"os"
	"strings"
	"sync"

	"inspector/pkg/log"

	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

type Config struct {
	Viper *viper.Viper
}

var (
	configVar string
	Instance  Config
	once      sync.Once
)

func NewInstance(configName string) Config {
	if len(configName) > 0 {
		Instance = ConfigInit(configName)
	} else {
		Instance = ConfigInit("config")
	}
	return Instance
}

func ConfigInit(cfgName string) Config {
	once.Do(func() {
		Instance = ConfigInitWithPrefix("", cfgName)
	})
	return Instance
}

func ConfigInitWithPrefix(envPrefix string, cfgName string) Config {
	log.Infof("ConfigInitWithPrefix")
	pflag.Parse()
	v := viper.New()
	config := Config{Viper: v}
	Instance = config
	vp := config.Viper
	err := vp.BindPFlags(pflag.CommandLine)
	if err != nil {
		log.Errorf("bind pflag error: %v", err)
		return Config{}
	}
	// read from env
	vp.AutomaticEnv()
	// so that client.foo maps to MYAPP_CLIENT_FOO
	vp.SetEnvPrefix(envPrefix)
	vp.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

	env := os.Getenv("RUNNING_ENV")
	if configVar != "" {
		vp.SetConfigFile(configVar)
	} else {
		vp.SetConfigName(cfgName) // name of config file (without extension)
		if env == "prod" {
			vp.AddConfigPath("configs/prod")
		} else if env == "test" {
			vp.AddConfigPath("configs/test")
		} else {
			vp.AddConfigPath("configs/dev")
		}
	}
	fmt.Println("Config paths:", viper.AllSettings()["configPaths"])

	if err := vp.ReadInConfig(); err != nil {
		panic(fmt.Errorf("error reading config: %s", err))
	}
	fmt.Printf("Using configuration file '%s'\n", vp.ConfigFileUsed())
	return config
}
